﻿
namespace Mulala.Cavan.Application.MainBoundedContext
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Mulala.Cavan.Application.Seedwork;
    using Mulala.Cavan.Core.Persistent;
    using Mulala.Cavan.Domain.Seedwork;
    using Mulala.Cavan.Core.MyException;
    using Mulala.Cavan.Core.Message;
    using Spring.Context;
    using Spring.Context.Support;
    using Mulala.Cavan.Core.Extension;
    using Mulala.Cavan.Domain.MainBoundedContext.MulalaModule;

    public abstract class ReadAppService<T, TID, TSearch, TRepository> : AppService, IReadAppService<T, TID, TSearch>
        where T : class, IPersistentObjectWithTypedId<TID>
        where TRepository : class, IRepository<T, TSearch>
        where TSearch : class, ISearch<TID>
    {
        #region members
        #endregion members

        #region IReadFacade
        public virtual T GetById(TID id)
        {
            try
            {
                var t = Repository.Get(id);
                return t;
            }
            catch (DaoException)
            {
                throw;
            }
            catch (Exception ex)
            {
                Messages.AddException(this, "exception", ex);
            }
            return default(T);
        }

        public virtual IEnumerable<T> GetBySearch(TSearch searchParams)
        {
            try
            {
                IApplicationContext context = ContextRegistry.GetContext();

                ISpecification<T, TSearch> specification = SpecificationFactory.CreateSpecification<T, TSearch>(searchParams) as ISpecification<T, TSearch>;
                specification.SearchParams = searchParams;

                IList<T> result = null;
                if (searchParams.CurrentPage > 0)
                {
                    result = Repository.GetPageList(specification).ToList();
                }
                else
                {
                    result = Repository.GetAll(specification).ToList();
                }
                if (result.Is())
                {
                    return result;
                }
                return new List<T>();
            }
            catch (DaoException)
            {
                throw; // DB connection in troubles. Need to restart dao facotory
            }
            catch (Exception ex)
            {
                Messages.AddException(this, "异常", ex);
            }
            return new List<T>();
        }

        public virtual T GetSingleBySearch(TSearch searchParams)
        {
            try
            {
                ISpecification<T, TSearch> specification = SpecificationFactory.CreateSpecification<T, TSearch>(searchParams) as ISpecification<T, TSearch>;

                var result = Repository.Get(specification);
                if (result.Is())
                {
                    return result;
                }
            }
            catch (DaoException)
            {
                throw;
            }
            catch (Exception ex)
            {
                Messages.AddException(this, "异常", ex);
            }
            return default(T);
        }

        public virtual IEnumerable<T> GetBySearch(TSearch searchParams,out long total)
        {
            total = 0;
            try
            {
                IApplicationContext context = ContextRegistry.GetContext();
                ISpecification<T, TSearch> specification = SpecificationFactory.CreateSpecification<T, TSearch>(searchParams) as ISpecification<T, TSearch>;
                var result = Repository.GetPageList(out total, specification).ToList();
                if (result.Is())
                {
                    return result;
                }
            }
            catch (DaoException)
            {
                throw; // DB connection in troubles. Need to restart dao facotory
            }
            catch (Exception ex)
            {
                Messages.AddException(this, "异常", ex);
            }
            return new List<T>();
        }

        public virtual long GetCount(TSearch searchParams)
        {
            try
            {
                IApplicationContext context = ContextRegistry.GetContext();
                ISpecification<T, TSearch> specification = SpecificationFactory.CreateSpecification<T, TSearch>(searchParams) as ISpecification<T, TSearch>;
                var result = Repository.GetCount(specification);
                if (result.Is())
                {
                    return result;
                }
            }
            catch (DaoException)
            {
                throw; // DB connection in troubles. Need to restart dao facotory
            }
            catch (Exception ex)
            {
                Messages.AddException(this, "异常", ex);
            }
            return 0;
        }
        #endregion IReadFacade

        #region DAO
        public virtual TRepository Repository { get; set; }
        #endregion D
    }
}